/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.web.io;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

/**
 * Wrapper that allow to modify the comportment of a <code>ServletContext</code>
 * without rewriting all methods.
 */
public class ServletContextWrapper
    implements ServletContext
{

  /**
   * the wrapped <code>ServletContext</code>.
   */
  private ServletContext servletContext;



  /**
   * Constructor.
   * 
   * @param servletContext
   *          the wrapped <code>ServletContext</code>
   */
  public ServletContextWrapper(final ServletContext servletContext)
  {
    this.servletContext = servletContext;
  }



  /**
   * Returns the servlet container attribute with the given name, or
   * <code>null</code> if there is no attribute by that name. An attribute
   * allows a servlet container to give the servlet additional information not
   * already provided by this interface. See your server documentation for
   * information about its attributes. A list of supported attributes can be
   * retrieved using <code>getAttributeNames</code>.
   * <p>
   * The attribute is returned as a <code>java.lang.Object</code> or some
   * subclass. Attribute names should follow the same convention as package
   * names. The Java Servlet API specification reserves names matching
   * <code>java.*</code>, <code>javax.*</code>, and <code>sun.*</code>.
   * 
   * @param name
   *          a <code>String</code> specifying the name of the attribute
   * @return an <code>Object</code> containing the value of the attribute, or
   *         <code>null</code> if no attribute exists matching the given name
   * @see ServletContext#getAttributeNames
   * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
   */
  public Object getAttribute(final String name)
  {
    return servletContext.getAttribute(name);
  }



  /**
   * Returns an <code>Enumeration</code> containing the attribute names
   * available within this servlet context. Use the {@link #getAttribute} method
   * with an attribute name to get the value of an attribute.
   * 
   * @return an <code>Enumeration</code> of attribute names
   * @see javax.servlet.ServletContext#getAttributeNames()
   * @see #getAttribute
   */
  public Enumeration<?> getAttributeNames()
  {
    return servletContext.getAttributeNames();
  }



  /**
   * Returns a <code>ServletContext</code> object that corresponds to a
   * specified URL on the server.
   * <p>
   * This method allows servlets to gain access to the context for various parts
   * of the server, and as needed obtain {@link RequestDispatcher} objects from
   * the context. The given path must be begin with "/", is interpreted relative
   * to the server's document root and is matched against the context roots of
   * other web applications hosted on this container.
   * <p>
   * In a security conscious environment, the servlet container may return
   * <code>null</code> for a given URL.
   * 
   * @param uripath
   *          a <code>String</code> specifying the context path of another web
   *          application in the container.
   * @return the <code>ServletContext</code> object that corresponds to the
   *         named URL, or null if either none exists or the container wishes to
   *         restrict this access.
   * @see RequestDispatcher
   * @see javax.servlet.ServletContext#getContext(java.lang.String)
   */
  public ServletContext getContext(final String uripath)
  {
    return servletContext.getContext(uripath);
  }



  /**
   * Returns a <code>String</code> containing the value of the named
   * context-wide initialization parameter, or <code>null</code> if the
   * parameter does not exist.
   * <p>
   * This method can make available configuration information useful to an
   * entire "web application". For example, it can provide a webmaster's email
   * address or the name of a system that holds critical data.
   * 
   * @param name
   *          a <code>String</code> containing the name of the parameter whose
   *          value is requested
   * @return a <code>String</code> containing at least the servlet container
   *         name and version number
   * @see javax.servlet.ServletConfig#getInitParameter
   * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
   */
  public String getInitParameter(final String name)
  {
    return servletContext.getInitParameter(name);
  }



  /**
   * Returns the names of the context's initialization parameters as an
   * <code>Enumeration</code> of <code>String</code> objects, or an empty
   * <code>Enumeration</code> if the context has no initialization parameters.
   * 
   * @return an <code>Enumeration</code> of <code>String</code> objects
   *         containing the names of the context's initialization parameters
   * @see javax.servlet.ServletConfig#getInitParameter
   * @see javax.servlet.ServletContext#getInitParameterNames()
   */
  public Enumeration<?> getInitParameterNames()
  {
    return servletContext.getInitParameterNames();
  }



  /**
   * Returns the major version of the Java Servlet API that this servlet
   * container supports.
   * 
   * @return the major version of the Java Servlet API that this servlet
   *         container supports
   * @see javax.servlet.ServletContext#getMajorVersion()
   */
  public int getMajorVersion()
  {
    return servletContext.getMajorVersion();
  }



  /**
   * Returns the MIME type of the specified file, or <code>null</code> if the
   * MIME type is not known. The MIME type is determined by the configuration of
   * the servlet container, and may be specified in a web application deployment
   * descriptor. Common MIME types are <code>"text/html"</code> and
   * <code>"image/gif"</code>.
   * 
   * @param file
   *          a <code>String</code> specifying the name of a file
   * @return a <code>String</code> specifying the file's MIME type
   * @see javax.servlet.ServletContext#getMimeType(java.lang.String)
   */
  public String getMimeType(final String file)
  {
    return servletContext.getMimeType(file);
  }



  /**
   * Returns the minor version of the Servlet API that this servlet container
   * supports.
   * 
   * @return the minor version of the Servlet API that this servlet container
   *         supports
   * @see javax.servlet.ServletContext#getMinorVersion()
   */
  public int getMinorVersion()
  {
    return servletContext.getMinorVersion();
  }



  /**
   * Returns a {@link RequestDispatcher} object that acts as a wrapper for the
   * named servlet.
   * <p>
   * Servlets (and JSP pages also) may be given names via server administration
   * or via a web application deployment descriptor. A servlet instance can
   * determine its name using {@link javax.servlet.ServletConfig#getServletName}.
   * <p>
   * This method returns <code>null</code> if the <code>ServletContext</code>
   * cannot return a <code>RequestDispatcher</code> for any reason.
   * 
   * @param name
   *          a <code>String</code> specifying the name of a servlet to wrap
   * @return a <code>RequestDispatcher</code> object that acts as a wrapper
   *         for the named servlet, or <code>null</code> if the
   *         <code>ServletContext</code> cannot return a
   *         <code>RequestDispatcher</code>
   * @see RequestDispatcher
   * @see ServletContext#getContext
   * @see javax.servlet.ServletConfig#getServletName
   * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
   */
  public RequestDispatcher getNamedDispatcher(final String name)
  {
    return servletContext.getNamedDispatcher(name);
  }



  /**
   * Returns a <code>String</code> containing the real path for a given
   * virtual path. For example, the path "/index.html" returns the absolute file
   * path on the server's filesystem would be served by a request for
   * "http://host/contextPath/index.html", where contextPath is the context path
   * of this ServletContext..
   * <p>
   * The real path returned will be in a form appropriate to the computer and
   * operating system on which the servlet container is running, including the
   * proper path separators. This method returns <code>null</code> if the
   * servlet container cannot translate the virtual path to a real path for any
   * reason (such as when the content is being made available from a
   * <code>.war</code> archive).
   * 
   * @param path
   *          a <code>String</code> specifying a virtual path
   * @return a <code>String</code> specifying the real path, or null if the
   *         translation cannot be performed
   * @see javax.servlet.ServletContext#getRealPath(java.lang.String)
   */
  public String getRealPath(final String path)
  {
    return servletContext.getRealPath(path);
  }



  /**
   * Returns a {@link RequestDispatcher} object that acts as a wrapper for the
   * resource located at the given path. A <code>RequestDispatcher</code>
   * object can be used to forward a request to the resource or to include the
   * resource in a response. The resource can be dynamic or static.
   * <p>
   * The pathname must begin with a "/" and is interpreted as relative to the
   * current context root. Use <code>getContext</code> to obtain a
   * <code>RequestDispatcher</code> for resources in foreign contexts. This
   * method returns <code>null</code> if the <code>ServletContext</code>
   * cannot return a <code>RequestDispatcher</code>.
   * 
   * @param path
   *          a <code>String</code> specifying the pathname to the resource
   * @return a <code>RequestDispatcher</code> object that acts as a wrapper
   *         for the resource at the specified path, or <code>null</code> if
   *         the <code>ServletContext</code> cannot return a
   *         <code>RequestDispatcher</code>
   * @see RequestDispatcher
   * @see ServletContext#getContext
   * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
   */
  public RequestDispatcher getRequestDispatcher(final String path)
  {
    return servletContext.getRequestDispatcher(path);
  }



  /**
   * Returns a URL to the resource that is mapped to a specified path. The path
   * must begin with a "/" and is interpreted as relative to the current context
   * root.
   * <p>
   * This method allows the servlet container to make a resource available to
   * servlets from any source. Resources can be located on a local or remote
   * file system, in a database, or in a <code>.war</code> file.
   * <p>
   * The servlet container must implement the URL handlers and
   * <code>URLConnection</code> objects that are necessary to access the
   * resource.
   * <p>
   * This method returns <code>null</code> if no resource is mapped to the
   * pathname.
   * <p>
   * Some containers may allow writing to the URL returned by this method using
   * the methods of the URL class.
   * <p>
   * The resource content is returned directly, so be aware that requesting a
   * <code>.jsp</code> page returns the JSP source code. Use a
   * <code>RequestDispatcher</code> instead to include results of an
   * execution.
   * <p>
   * This method has a different purpose than
   * <code>java.lang.Class.getResource</code>, which looks up resources based
   * on a class loader. This method does not use class loaders.
   * 
   * @param path
   *          a <code>String</code> specifying the path to the resource
   * @return the resource located at the named path, or <code>null</code> if
   *         there is no resource at that path
   * @exception MalformedURLException
   *              if the pathname is not given in the correct form
   * @see javax.servlet.ServletContext#getResource(java.lang.String)
   */
  public URL getResource(final String path)
      throws MalformedURLException
  {
    return servletContext.getResource(path);
  }



  /**
   * Returns the resource located at the named path as an
   * <code>InputStream</code> object.
   * <p>
   * The data in the <code>InputStream</code> can be of any type or length.
   * The path must be specified according to the rules given in
   * <code>getResource</code>. This method returns <code>null</code> if no
   * resource exists at the specified path.
   * <p>
   * Meta-information such as content length and content type that is available
   * via <code>getResource</code> method is lost when using this method.
   * <p>
   * The servlet container must implement the URL handlers and
   * <code>URLConnection</code> objects necessary to access the resource.
   * <p>
   * This method is different from
   * <code>java.lang.Class.getResourceAsStream</code>, which uses a class
   * loader. This method allows servlet containers to make a resource available
   * to a servlet from any location, without using a class loader.
   * 
   * @param path
   *          a <code>String</code> specifying the path to the resource
   * @return the <code>InputStream</code> returned to the servlet, or
   *         <code>null</code> if no resource exists at the specified path
   * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
   */
  public InputStream getResourceAsStream(final String path)
  {
    return servletContext.getResourceAsStream(path);
  }



  /**
   * Returns a directory-like listing of all the paths to resources within the
   * web application whose longest sub-path matches the supplied path argument.
   * Paths indicating subdirectory paths end with a '/'. The returned paths are
   * all relative to the root of the web application and have a leading '/'. For
   * example, for a web application containing<br>
   * <br>
   * /welcome.html<br>
   * /catalog/index.html<br>
   * /catalog/products.html<br>
   * /catalog/offers/books.html<br>
   * /catalog/offers/music.html<br>
   * /customer/login.jsp<br>
   * /WEB-INF/web.xml<br>
   * /WEB-INF/classes/com.acme.OrderServlet.class,<br>
   * <br>
   * getResourcePaths("/") returns {"/welcome.html", "/catalog/", "/customer/",
   * "/WEB-INF/"}<br>
   * getResourcePaths("/catalog/") returns {"/catalog/index.html",
   * "/catalog/products.html", "/catalog/offers/"}.<br>
   * 
   * @param path
   *          the partial path used to match the resources, which must start
   *          with a /
   * @return a Set containing the directory listing, or null if there are no
   *         resources in the web application whose path begins with the
   *         supplied path.
   * @since Servlet 2.3
   * @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
   */
  @SuppressWarnings("unchecked")
  public Set<String> getResourcePaths(final String path)
  {
    return servletContext.getResourcePaths(path);
  }



  /**
   * Returns the name and version of the servlet container on which the servlet
   * is running.
   * <p>
   * The form of the returned string is <i>servername</i>/<i>versionnumber</i>.
   * For example, the JavaServer Web Development Kit may return the string
   * <code>JavaServer Web Dev Kit/1.0</code>.
   * <p>
   * The servlet container may return other optional information after the
   * primary string in parentheses, for example,
   * <code>JavaServer Web Dev Kit/1.0 (JDK 1.1.6; Windows NT 4.0 x86)</code>.
   * 
   * @return a <code>String</code> containing at least the servlet container
   *         name and version number
   * @see javax.servlet.ServletContext#getServerInfo()
   */
  public String getServerInfo()
  {
    return servletContext.getServerInfo();
  }



  /**
   * This method was originally defined to retrieve a servlet from a
   * <code>ServletContext</code>. In this version, this method always returns
   * <code>null</code> and remains only to preserve binary compatibility. This
   * method will be permanently removed in a future version of the Java Servlet
   * API.
   * <p>
   * In lieu of this method, servlets can share information using the
   * <code>ServletContext</code> class and can perform shared business logic
   * by invoking methods on common non-servlet classes.
   * 
   * @param name
   *          name of the servlet
   * @throws ServletException
   *           if an error occurred
   * @return <code>null</code>
   * @deprecated As of Java Servlet API 2.1, with no direct replacement.
   * @see javax.servlet.ServletContext#getServlet(java.lang.String)
   */
  @Deprecated
  public Servlet getServlet(final String name)
      throws ServletException
  {
    return servletContext.getServlet(name);
  }



  /**
   * Returns the name of this web application correponding to this
   * ServletContext as specified in the deployment descriptor for this web
   * application by the display-name element.
   * 
   * @return The name of the web application or null if no name has been
   *         declared in the deployment descriptor.
   * @since Servlet 2.3
   * @see javax.servlet.ServletContext#getServletContextName()
   */
  public String getServletContextName()
  {
    return servletContext.getServletContextName();
  }



  /**
   * <p>
   * This method was originally defined to return an <code>Enumeration</code>
   * of all the servlet names known to this context. In this version, this
   * method always returns an empty <code>Enumeration</code> and remains only
   * to preserve binary compatibility. This method will be permanently removed
   * in a future version of the Java Servlet API.
   * 
   * @return an empty <code>Enumeration</code>
   * @deprecated As of Java Servlet API 2.1, with no replacement.
   * @see javax.servlet.ServletContext#getServletNames()
   */
  @Deprecated
  public Enumeration<?> getServletNames()
  {
    return servletContext.getServletNames();
  }



  /**
   * <p>
   * This method was originally defined to return an <code>Enumeration</code>
   * of all the servlets known to this servlet context. In this version, this
   * method always returns an empty enumeration and remains only to preserve
   * binary compatibility. This method will be permanently removed in a future
   * version of the Java Servlet API.
   * 
   * @return an empty <code>Enumeration</code>
   * @deprecated As of Java Servlet API 2.0, with no replacement.
   * @see javax.servlet.ServletContext#getServlets()
   */
  @Deprecated
  public Enumeration<?> getServlets()
  {
    return servletContext.getServlets();
  }



  /**
   * {@link #log(String message, Throwable throwable)} instead.
   * <p>
   * This method was originally defined to write an exception's stack trace and
   * an explanatory error message to the servlet log file.
   * 
   * @param exception
   *          the <code>Exception</code> error or exception
   * @param msg
   *          a <code>String</code> that describes the error or exception
   * @deprecated As of Java Servlet API 2.1, use
   * @see javax.servlet.ServletContext#log(java.lang.Exception,
   *      java.lang.String)
   */
  @Deprecated
  public void log(final Exception exception, final String msg)
  {
    servletContext.log(exception, msg);
  }



  /**
   * Writes an explanatory message and a stack trace for a given
   * <code>Throwable</code> exception to the servlet log file. The name and
   * type of the servlet log file is specific to the servlet container, usually
   * an event log.
   * 
   * @param message
   *          a <code>String</code> that describes the error or exception
   * @param throwable
   *          the <code>Throwable</code> error or exception
   * @see javax.servlet.ServletContext#log(java.lang.String,
   *      java.lang.Throwable)
   */
  public void log(final String message, final Throwable throwable)
  {
    servletContext.log(message, throwable);
  }



  /**
   * Writes the specified message to a servlet log file, usually an event log.
   * The name and type of the servlet log file is specific to the servlet
   * container.
   * 
   * @param msg
   *          a <code>String</code> specifying the message to be written to
   *          the log file
   * @see javax.servlet.ServletContext#log(java.lang.String)
   */
  public void log(final String msg)
  {
    servletContext.log(msg);
  }



  /**
   * Removes the attribute with the given name from the servlet context. After
   * removal, subsequent calls to {@link #getAttribute} to retrieve the
   * attribute's value will return <code>null</code>.
   * <p>
   * If listeners are configured on the <code>ServletContext</code> the
   * container notifies them accordingly.
   * 
   * @param name
   *          a <code>String</code> specifying the name of the attribute to be
   *          removed
   * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
   */
  public void removeAttribute(final String name)
  {
    servletContext.removeAttribute(name);
  }



  /**
   * Binds an object to a given attribute name in this servlet context. If the
   * name specified is already used for an attribute, this method will replace
   * the attribute with the new to the new attribute.
   * <p>
   * If listeners are configured on the <code>ServletContext</code> the
   * container notifies them accordingly.
   * <p>
   * If a null value is passed, the effect is the same as calling
   * <code>removeAttribute()</code>.
   * <p>
   * Attribute names should follow the same convention as package names. The
   * Java Servlet API specification reserves names matching <code>java.*</code>,
   * <code>javax.*</code>, and <code>sun.*</code>.
   * 
   * @param name
   *          a <code>String</code> specifying the name of the attribute
   * @param object
   *          an <code>Object</code> representing the attribute to be bound
   * @see javax.servlet.ServletContext#setAttribute(java.lang.String,
   *      java.lang.Object)
   */
  public void setAttribute(final String name, final Object object)
  {
    servletContext.setAttribute(name, object);
  }



  /**
   * getter for the servletContext property.
   * 
   * @return the servletContext
   */
  public ServletContext getServletContext()
  {
    return servletContext;
  }



  /**
   * setter for the servletContext property.
   * 
   * @param servletContext
   *          the servletContext to set
   */
  public void setServletContext(final ServletContext servletContext)
  {
    this.servletContext = servletContext;
  }

}
